<script lang="ts" setup>
import type { allRolesType, Oauth2BasicUserInOrUpReq, Oauth2BasicUserVO, UpdateUserRolesReq } from '@/api/user/userType'
import { deleteUser, getUserPage, getUserRoleList, saveUser, updateUserRoles } from '@/api/user/userApi'
import router from '@/router/index'
import useLayoutStore from '@/store/modules/setting'
import useUserStore from '@/store/modules/user'
import { ElMessage } from 'element-plus'
import { nextTick, onMounted, reactive, ref } from 'vue'

// 使用用户小仓库
const userStore = useUserStore()
// 默认页码
const currentPage = ref<number>(1)
// 默认页行数
const pageSize = ref<number>(10)
// 数据总数
const total = ref<number>(0)
// 用户数据数组
const userList = ref<Oauth2BasicUserVO[]>()
// 用户名
const userName = ref<string>('')
// 定义响应式数据控制抽屉展示或者隐藏
const drawer = ref<boolean>(false)
// 定义响应式数据控制抽屉标题
const drawerTitle = ref<string>('')
// 收集用户响应式数据
const userParams = reactive<Oauth2BasicUserInOrUpReq>({
/** 用户名、昵称 */
  name: '',
  /** 账号 */
  account: '',
  /** 密码 */
  password: '',
  /** 手机号 */
  mobile: '',
  /** 邮箱 */
  email: '',
})
// 定义应式数据控制抽屉里的账号密码是否展示
const isShowPassword = ref<boolean>(true)
// 定义操作用户表单校验规则
const operateUserRules = {
  // 用户名
  account: [{ required: true, message: '请输入用户账号', trigger: 'blur' }],
}
// 获取operateUserFormRef 组件实例
const operateUserFormRef = ref()
// 定义响应式数据控制分配角色抽屉展示或者隐藏
const drawer2 = ref<boolean>(false)
// 定义响应式数据控制角色列表是否全选
const checkAll = ref<boolean>(false)
// 定义响应式数据设置角色列表不确定样式
const isIndeterminate = ref<boolean>(false)
// 定义响应式数据设置角色列中明细数据
const checkedRoles = ref<allRolesType>([])
// 定义响应式数据设置所有角色列表
const allRoles = ref<allRolesType>([])
// 定义响应式数据设置表格复选框选中的选中项
const selectedIds = ref<number[]>([])

// 使用layout组件小仓库
const layoutStore = useLayoutStore()

// 组件挂载
onMounted(() => {
  // 默认当前页是1
  currentPage.value = 1
  // 默认每页10条数据
  pageSize.value = 10
  // 默认用户名是空
  userName.value = ''
  // 挂载时默认查询用户信息
  getUserPageData()
})

/**
 * 用户分页查询
 *
 * 此函数尝试通过调用getUserPage方法来获取用户数据，并更新用户列表和总用户数
 * 如果请求成功，它会更新userList和total的值
 * 如果请求失败，它会捕获异常并显示错误消息
 */
async function getUserPageData() {
  try {
    // 调用getUserPage方法获取用户数据
    const result: any = await getUserPage({
      userName: userName.value,
      pageReq: {
        current: currentPage.value,
        size: pageSize.value,
      },
    })
    // 如果请求成功，更新用户列表和总用户数
    if (result.success) {
      userList.value = result.data
      total.value = result.total
    }
  }
  catch (error) {
    // 处理异常
    let errorMessage = '未知错误'
    if (error instanceof Error) {
      errorMessage = error.message
    }
    // 显示错误消息
    ElMessage({
      message: `查询失败: ${errorMessage || '未知错误'}`,
      type: 'error',
    })
  }
}

// 分页器下拉菜单自定义事件
function handerPageData() {
  getUserPageData()
}

// 添加用户按钮方法-打开抽屉
function addUser() {
  // 展示抽屉
  drawer.value = true
  // 抽屉标题
  drawerTitle.value = '新增用户'
  // 使用Object.assign() 清空抽屉
  Object.assign(userParams, {
    id: '',
    name: '',
    account: '',
    password: '',
    mobile: '',
    email: '',
  })
  // 展示账号密码
  isShowPassword.value = true

  // 清楚上一次的 operateUserFormRef 校验信息
  nextTick(() => {
    operateUserFormRef.value.clearValidate('account')
  })
}

// 修改用户按钮方法-打开抽屉并赋值当前行数据 updateUser 传入参数是当前行数据 row
function updateUser(row: Oauth2BasicUserVO) {
  // 展示抽屉
  drawer.value = true
  // 抽屉标题
  drawerTitle.value = '修改用户'
  // 存储收集已有的账号信息
  Object.assign(userParams, row)
  // 去除账号密码元素
  userParams.password = ''
  // 不展示账号密码
  isShowPassword.value = false

  // 清楚上一次的 operateUserFormRef 校验信息
  nextTick(() => {
    operateUserFormRef.value.clearValidate('account')
  })
}

/**
 * 保存用户信息的异步函数
 * 此函数首先尝试验证用户信息表单的输入如果验证失败，则直接抛出异常
 * 接着，调用saveUser函数尝试保存用户信息如果保存成功，显示成功消息，
 * 并根据是否是当前用户，决定是否重定向到认证页面
 * 最后，关闭操作抽屉并重新获取用户列表数据
 * 如果保存失败，则显示失败消息
 * 异常处理包括表单验证失败和未知错误
 */
async function onSaveUser() {
  try {
    // operateUserFormRef 校验失败直接异常返回
    await operateUserFormRef.value.validate()
    const result: any = await saveUser(userParams)
    if (result.success) {
      // 提示新增成功
      ElMessage({
        message: '操作成功',
        type: 'success',
      })
      // 判断如果修改的是当前的用户的话，重新查询用户信息，放入pinia中，查不到就重新向至 /OAuth2Redirect
      if (Number(userParams.id) === userStore.userId) {
        // 清楚token
        userStore.$reset()
        router.push({ path: '/OAuth2Redirect' })
      }
      // 关闭抽屉
      drawer.value = false
      // 重新执行默认查询
      // 默认当前页是1
      currentPage.value = 1
      // 默认每页10条数据
      pageSize.value = 10
      // 默认用户名是空
      userName.value = ''
      // 挂载时默认查询用户信息
      getUserPageData()
    }
    else {
      // 提示新增失败
      ElMessage({
        message: '新增失败',
        type: 'error',
      })
    }
  }
  catch (error) {
    // 处理异常
    let errorMessage = '未知错误'
    if (error instanceof Error) {
      errorMessage = error.message
    }
    else {
      errorMessage = '表单校验失败'
    }
    ElMessage({
      message: `保存失败: ${errorMessage}`,
      type: 'error',
    })
  }
}

// 关闭用户信息新增或者修改抽屉
function cancel() {
  // 关闭
  drawer.value = false

  // 使用Object.assign() 清空抽屉
  Object.assign(userParams, {
    id: '',
    name: '',
    account: '',
    password: '',
    mobile: '',
    email: '',
  })

  // 展示账号密码
  isShowPassword.value = true
}

// 分配角色按钮
async function setRole(row: Oauth2BasicUserVO) {
  // 打开抽屉
  // drawer2.value = true
  // 存储已有的用户信息
  Object.assign(userParams, row)

  // 获取指定用户角色清单以及所有角色清单
  const oauth2BasicUserRoleReq = { id: row.id as number }

  const result: any = await getUserRoleList(oauth2BasicUserRoleReq)
  if (result.success) {
    // 获取用户角色清单
    checkedRoles.value = result.data.assignRoles
    // 获取所有角色清单
    allRoles.value = result.data.allRolesList

    // 如果选中的数量等于所有角色的数量，则点亮全选标识，否则不点亮
    const checkedCount = checkedRoles.value.length
    checkAll.value = checkedCount === allRoles.value.length
    // 如果部分的角色被选中，则点亮不确定点标识
    isIndeterminate.value = checkedRoles.value.length > 0 && checkedRoles.value.length < allRoles.value.length

    // 打开分配角色抽屉
    drawer2.value = true
  }
}

// 全选复选框的change事件
function handleCheckAllChange(val: boolean) {
  checkedRoles.value = val ? allRoles.value : []
  // 更新不确定状态
  isIndeterminate.value = false
}

// 全选明细框的change事件
function handleCheckedRolesChange() {
  const checkedCount = checkedRoles.value.length
  // 如果选中的数量等于所有角色的数量，则点亮全选标识，否则不点亮
  checkAll.value = checkedCount === allRoles.value.length

  // 如果选中的数量大于0且小于所有角色的数量，则点亮不确定标识，否则不点亮
  isIndeterminate.value = checkedCount > 0 && checkedCount < allRoles.value.length
}

// 分配角色确定按钮
async function onSaveUserRole() {
  // 收集参数
  const data: UpdateUserRolesReq = {
    id: userParams.id as number,
    roleIds: checkedRoles.value.map((item) => { return item.id as number }),
  }
  const result: any = await updateUserRoles(data)
  if (result.success) {
    ElMessage({
      message: '操作成功',
      type: 'success',
    })
    // 关闭 分配角色抽屉
    drawer2.value = false
    // 重新执行默认查询
    // 默认当前页是1
    currentPage.value = 1
    // 默认每页10条数据
    pageSize.value = 10
    // 默认用户名是空
    userName.value = ''
    // 挂载时默认查询用户信息
    getUserPageData()
  }
}

// 删除单个用户按钮
async function deleteOneUser(row: Oauth2BasicUserVO) {
  // 删除单个用户
  const result: any = await deleteUser({ ids: [row.id as number] })
  if (result.success && result.code === 200) {
    ElMessage({
      message: '删除成功',
      type: 'success',
    })
    // 重新执行默认查询
    // 默认当前页是1
    currentPage.value = 1
    // 默认每页10条数据
    pageSize.value = 10
    // 默认用户名是空
    userName.value = ''
    // 挂载时默认查询用户信息
    getUserPageData()
  }
  else {
    ElMessage({
      message: `删除失败,失败原因：${result.message}`,
      type: 'error',
    })
  }
}

// 表格多选框选中事件
function handleSelectionChange(val: Oauth2BasicUserVO[]) {
  // 收集选中行的所有id
  const selectedIdsArray = val.map(item => item.id as number)
  selectedIds.value = selectedIdsArray
}

// 删除多个用户按钮功能
async function deleteMoreUser() {
  // 删除多个用户
  const result: any = await deleteUser({ ids: selectedIds.value })
  if (result.success) {
    if (result.data) {
      ElMessage({
        message: '删除成功',
        type: 'success',
      })
      // 重新执行默认查询
      // 默认当前页是1
      currentPage.value = 1
      // 默认每页10条数据
      pageSize.value = 10
      // 默认用户名是空
      userName.value = ''
      // 挂载时默认查询用户信息
      getUserPageData()
    }
    else {
      ElMessage({
        message: '删除失败,请检查用户使用仍有关联角色未清楚',
        type: 'error',
      })
    }
  }
}

// 重置界面
function reset() {
  layoutStore.refresh = !layoutStore.refresh
}
</script>

<template>
  <!-- 查询条件 -->
  <el-card style="height: 75px;">
    <el-form :inline="true" class="form-inline">
      <el-form-item label="用户名">
        <el-input v-model="userName" placeholder="请输入用户名" />
      </el-form-item>
      <el-form-item>
        <el-button v-hasButton="`btn.user.page`" type="primary" icon="Search" @click="getUserPageData">
          查询
        </el-button>
        <el-button v-hasButton="`btn.user.page`" icon="Refresh" @click="reset">
          重置
        </el-button>
      </el-form-item>
    </el-form>
  </el-card>

  <!-- 查询结果列表 -->
  <el-card style="margin: 10px 0px;">
    <el-button v-hasButton="`btn.user.save`" type="primary" icon="Plus" @click="addUser">
      新增用户
    </el-button>
    <el-button v-hasButton="`btn.user.delete`" type="danger" :disabled="selectedIds.length === 0" icon="Delete" @click="deleteMoreUser">
      批量删除
    </el-button>
    <el-table style="margin: 10px 0px;" :data="userList" :border="true" @selection-change="handleSelectionChange">
      <el-table-column type="selection" align="center" width="50px" />
      <el-table-column type="index" label="#" align="center" width="50px" />
      <el-table-column prop="id" label="ID" align="center" />
      <el-table-column prop="name" label="用户名" align="center" />
      <el-table-column prop="account" label="账号" align="center" />
      <el-table-column prop="mobile" label="手机号" align="center" />
      <el-table-column prop="email" label="邮箱" align="center" />
      <el-table-column prop="createTime" label="创建时间" align="center" />
      <el-table-column prop="creatorName" label="创建人" align="center" />
      <el-table-column prop="modifyTime" label="修改时间" align="center" />
      <el-table-column prop="modifierName" label="修改人" align="center" />
      <el-table-column label="操作" width="350px" align="center">
        <template #default="scope">
          <el-button v-hasButton="`btn.user.userRole`" type="primary" icon="Pointer" @click="setRole(scope.row)">
            分配角色
          </el-button>
          <el-button v-hasButton="`btn.user.save`" type="primary" icon="EditPen" @click="updateUser(scope.row)">
            修改
          </el-button>
          <el-popconfirm :title="`确定删除${scope.row.name}吗？`" @confirm="deleteOneUser(scope.row)">
            <template #reference>
              <el-button v-hasButton="`btn.user.delete`" type="danger" icon="Delete">
                删除
              </el-button>
            </template>
          </el-popconfirm>
        </template>
      </el-table-column>
    </el-table>
    <!-- 分页器 -->
    <el-pagination
      v-model:current-page="currentPage"
      v-model:page-size="pageSize"
      :page-sizes="[10, 20, 30, 40, 50]"
      layout="prev, pager, next, jumper,->, sizes, total"
      :total="total"
      @current-change="getUserPageData"
      @size-change="handerPageData"
    />
  </el-card>

  <!-- 用户信息编辑抽屉：完成添加新的用户账号或者更新已有的账号信息 -->
  <el-drawer v-model="drawer">
    <template #header>
      <h4>{{ drawerTitle }}</h4>
    </template>
    <template #default>
      <el-form ref="operateUserFormRef" :model="userParams" :rules="operateUserRules">
        <el-form-item label="用户名称" prop="name">
          <el-input v-model="userParams.name" placeholder="请输入用户名称" />
        </el-form-item>
        <el-form-item label="用户账号" prop="account">
          <el-input v-model="userParams.account" placeholder="请输入用户账号" />
        </el-form-item>
        <el-form-item v-if="isShowPassword" label="用户密码" prop="password">
          <el-input v-model="userParams.password" placeholder="请输入用户密码" />
        </el-form-item>
        <el-form-item label="用户手机" prop="mobile">
          <el-input v-model="userParams.mobile" placeholder="请输入用户手机号" />
        </el-form-item>
        <el-form-item label="用户邮箱" prop="email">
          <el-input v-model="userParams.email" placeholder="请输入用户电子邮箱" />
        </el-form-item>
      </el-form>
    </template>
    <template #footer>
      <div style="flex: auto">
        <el-button @click="cancel">
          取消
        </el-button>
        <el-button v-hasButton="`btn.user.save`" type="primary" @click="onSaveUser">
          确定
        </el-button>
      </div>
    </template>
  </el-drawer>

  <!-- 分配角色抽屉 -->
  <el-drawer v-model="drawer2">
    <template #header>
      <h4>分配角色</h4>
    </template>
    <template #default>
      <el-form>
        <el-form-item label="用户名称">
          <el-input v-model="userParams.name" placeholder="请输入用户名称" :disabled="true" />
        </el-form-item>
        <el-form-item label="角色列表">
          <el-checkbox v-model="checkAll" :indeterminate="isIndeterminate" @change="handleCheckAllChange">
            全选
          </el-checkbox>
          <el-checkbox-group v-model="checkedRoles" @change="handleCheckedRolesChange">
            <el-checkbox v-for="(role, index) in allRoles" :key="index" :label="role" :value="role">
              {{ role.roleName }}
            </el-checkbox>
          </el-checkbox-group>
        </el-form-item>
      </el-form>
    </template>
    <template #footer>
      <div style="flex: auto">
        <el-button type="primary" @click="drawer2 = false">
          取消
        </el-button>
        <el-button v-hasButton="`btn.user.updateUserRole`" type="primary" @click="onSaveUserRole">
          确定
        </el-button>
      </div>
    </template>
  </el-drawer>
</template>

<style scoped>
.form-inline {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
</style>
